﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ShredTheLog.Api.DataContracts;
using ShredTheLog.Api.DataContracts.TextChat;
using System.Diagnostics.Contracts;

namespace ShredTheLog.Api
{
    [ContractClass(typeof(ShredClient_Contract))]
    public interface IShredClient
    {
        TimeSpan UpdatePeriod { get; }
        IObservable<IContactListResponse> AddContact(ISessionCredentials user, IUserInfo contact);
        IObservable<IContactListResponse> DeleteContact(ISessionCredentials user, IUserInfo contact);
        IObservable<IUserSearchResponse> SearchUsers(Language? knownLanguage, Language? practicingLanguage, bool? chatsOnline, Country? country, int? minAge, int? maxAge, string firstName, string lastName, string location, IUserInfo lastViewedUser);
        IObservable<IFullUserInfo> GetFullUserInfo(IUserInfo user);
        IObservable<ISessionCredentials> LogIn(string userName, string password);
        IObservable<IBasicUserInfo[]> GetVoiceChatUsers();
        IObservable<IShortUserInfo[]> GetTextChatUsers();
        IObservable<ILast15UserInfo[]> GetLast15Users();
        IObservable<IContact[]> GetContactList(ISessionCredentials user);
        IObservable<IInitialTextChatInfo> JoinTextChat(ISessionCredentials user);
        IObservable<IInitialTextChatInfo> JoinTextChatAnonymously();
        ITextChat CreateTextChat(ISessionCredentials credentials, IInitialTextChatInfo initialInfo);
    }

    [ContractClassFor(typeof(IShredClient))]
    internal abstract class ShredClient_Contract : IShredClient
    {
        TimeSpan IShredClient.UpdatePeriod { get { throw new NotImplementedException(); } }

        IObservable<IContactListResponse> IShredClient.AddContact(ISessionCredentials user, IUserInfo contact)
        {
            Contract.Requires(user != null);
            Contract.Requires(contact != null);
            Contract.Ensures(Contract.Result<IObservable<IContactListResponse>>() != null);
            throw new NotImplementedException();
        }

        IObservable<IContactListResponse> IShredClient.DeleteContact(ISessionCredentials user, IUserInfo contact)
        {
            Contract.Requires(user != null);
            Contract.Requires(contact != null);
            Contract.Ensures(Contract.Result<IObservable<IContactListResponse>>() != null);
            throw new NotImplementedException();
        }

        IObservable<IUserSearchResponse> IShredClient.SearchUsers(Language? knownLanguage, Language? practicingLanguage, bool? chatsOnline, Country? country, int? minAge, int? maxAge, string firstName, string lastName, string location, IUserInfo lastViewedUser)
        {
            Contract.Ensures(Contract.Result<IObservable<IUserSearchResponse>>() != null);
            throw new NotImplementedException();
        }

        IObservable<IFullUserInfo> IShredClient.GetFullUserInfo(IUserInfo user)
        {
            Contract.Requires(user != null);
            Contract.Ensures(Contract.Result<IObservable<IFullUserInfo>>() != null);
            throw new NotImplementedException();
        }

        IObservable<ISessionCredentials> IShredClient.LogIn(string userName, string password)
        {
            Contract.Requires(!String.IsNullOrEmpty(userName));
            Contract.Requires(password != null);
            Contract.Ensures(Contract.Result<IObservable<ISessionCredentials>>() != null);
            throw new NotImplementedException();
        }

        IObservable<IBasicUserInfo[]> IShredClient.GetVoiceChatUsers()
        {
            Contract.Ensures(Contract.Result<IObservable<IBasicUserInfo[]>>() != null);
            throw new NotImplementedException();
        }

        IObservable<IShortUserInfo[]> IShredClient.GetTextChatUsers()
        {
            Contract.Ensures(Contract.Result<IObservable<IShortUserInfo[]>>() != null);
            throw new NotImplementedException();
        }

        IObservable<ILast15UserInfo[]> IShredClient.GetLast15Users()
        {
            Contract.Ensures(Contract.Result<IObservable<ILast15UserInfo[]>>() != null);
            throw new NotImplementedException();
        }

        IObservable<IContact[]> IShredClient.GetContactList(ISessionCredentials user)
        {
            Contract.Requires(user != null);
            Contract.Ensures(Contract.Result<IObservable<IContact[]>>() != null);
            throw new NotImplementedException();
        }

        IObservable<IInitialTextChatInfo> IShredClient.JoinTextChat(ISessionCredentials user)
        {
            Contract.Requires(user != null);
            Contract.Ensures(Contract.Result<IObservable<IInitialTextChatInfo>>() != null);
            throw new NotImplementedException();
        }

        IObservable<IInitialTextChatInfo> IShredClient.JoinTextChatAnonymously()
        {
            Contract.Ensures(Contract.Result<IObservable<IInitialTextChatInfo>>() != null);
            throw new NotImplementedException();
        }

        ITextChat IShredClient.CreateTextChat(ISessionCredentials credentials, IInitialTextChatInfo initialInfo)
        {
            Contract.Requires(initialInfo != null);
            Contract.Ensures(Contract.Result<ITextChat>() != null);
            throw new NotImplementedException();
        }
    }

    public interface IUserSearchResponse
    {
        /// <summary>
        /// Количество непросмотренных записей включая текущую страницу
        /// </summary>
        /// <remarks>
        /// [Общее число записей] - ([Номер просматриваемой страницы (нумерация с 1)] - 1) * [Количество записей на страницу]
        /// </remarks>
        int RestCount { get; }

        IShortUserInfo[] Users { get; }
    }

    public interface IContactListResponse
    {
        ContactListResponseKind Kind { get; }
    }

    public enum ContactListResponseKind
    {
        ContactAdded,
        AlreadyAdded,
        ContactDeleted
    }

    public interface IInitialTextChatInfo
    {
        int Uid { get; }
        Guid Guid { get; }
        IShortUserInfo[] OnlineUsers { get; }
    }
}
